package de.is24.nexus.yum.repository;

import static java.io.File.createTempFile;
import static java.lang.String.format;
import static java.net.InetAddress.getLocalHost;
import static org.freecompany.redline.header.Architecture.NOARCH;
import static org.freecompany.redline.header.Os.LINUX;
import static org.freecompany.redline.header.RpmType.BINARY;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.io.IOUtils;
import org.freecompany.redline.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class RepositoryRpmGenerator {
  private static final Logger log = LoggerFactory.getLogger(RepositoryRpmGenerator.class);
  private static final String DESCRIPTION_TEMPLATE =
    "Package which is generated by Sonatype Nexus to introduce versionized YUM repository views on Nexus repositories to a Redhat-like system. The package contains just a /etc/yum.repos.d/is24-rel-%s-%s.repo file, which contains a link to the specific Nexus repository.";
  private static final String SUMMARY_TEMPLATE =
    "Package which introduce the yum repository of all artifacts in repository %s in version %s to the system.";
  private final String baseUrl;
  private final String repositoryId;
  private final String version;
  private final File outputDirectory;

  public RepositoryRpmGenerator(String baseUrl, String repositoryId, String version, File outputDirectory) {
    this.baseUrl = baseUrl;
    this.repositoryId = repositoryId;
    this.version = version;
    this.outputDirectory = outputDirectory;
  }

  public void generateReleaseRpm() throws IOException, NoSuchAlgorithmException {
    File repoFile = createRepoFile();
    buildReleaseRpm(repoFile);
    repoFile.delete();
  }

  private void buildReleaseRpm(File repoFile) throws IOException, NoSuchAlgorithmException {
    Builder rpmBuilder = new Builder();
    rpmBuilder.setVendor("IS24");
    rpmBuilder.setGroup("is24");
    rpmBuilder.setPackager("Sonatype Nexus");
    rpmBuilder.setSummary(format(SUMMARY_TEMPLATE, repositoryId, version));
    rpmBuilder.setDescription(format(DESCRIPTION_TEMPLATE, repositoryId, version));
    try {
      rpmBuilder.setBuildHost(getLocalHost().getHostName());
    } catch (UnknownHostException e) {
      throw new RuntimeException("Could not determine hostname.", e);
    }
    rpmBuilder.setPackage(format("is24-rel-%s-%s-repo", repositoryId, version.toLowerCase()), "1", "1");
    rpmBuilder.setPlatform(NOARCH, LINUX);
    rpmBuilder.setType(BINARY);
    rpmBuilder.setSourceRpm("dummy-source-rpm-because-yum-needs-this");
    rpmBuilder.addFile(format("/etc/yum.repos.d/is24-rel-%s-%s.repo", repositoryId, version.toLowerCase()), repoFile,
      0755, null, "webadmin", "admins");
    rpmBuilder.build(outputDirectory);
    log.info("Built release rpm for repository {} and version {} to {}",
      new Object[] {
        repositoryId, version.toLowerCase(),
        outputDirectory
      });
  }

  private File createRepoFile() throws IOException {
    File tmpFile = createTempFile("repo", ".repo");
    OutputStream outputStream = new FileOutputStream(tmpFile);
    try {
      IOUtils.write(createRepoFileContent(), outputStream);
      log.info("Wrote content to repository rpm {}", tmpFile);
    } finally {
      outputStream.close();
    }
    return tmpFile;
  }

  private String createRepoFileContent() {
    StringBuilder builder = new StringBuilder();
    builder.append(format("[is24-rel-%s-%s]\n", repositoryId, version));
    builder.append(format("name = Immobilen Scout GmbH Versionized %s %s Repository\n", repositoryId, version));
    builder.append(format("baseurl = %s/service/local/yum/%s/%s\n", baseUrl, repositoryId, version));
    builder.append("enabled = 1\n");
    builder.append("protect = 0\n");
    builder.append("gpgcheck = 0\n");
    builder.append("metadata_expire = 30s\n");
    return builder.toString();
  }
}
